//   Copyright 2009
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

package com.navjagpal.notes;

import java.io.IOException;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Set;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ListActivity;
import android.content.ComponentName;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.TabHost;
import android.widget.AdapterView.AdapterContextMenuInfo;

import com.navjagpal.notes.NotesProvider.List;

public class Notes extends ListActivity {
  
    private Handler mHandler;
    private static final String SPREADSHEETS_AUTH_TOKEN_TYPE = "wise";
    private static final String DOCUMENTS_AUTH_TOKEN_TYPE = "writely";
    private static final int MENU_NEW_LIST = 0;
    private static final int MENU_SYNC = 1;
    private static final int DIALOG_NEW_LIST = 0;
    private static final int DIALOG_PROBLEM_CREATING_LIST = 1;
    private static final int DIALOG_SYNC_ERROR = 2;
    private static final int CONTEXT_DELETE = 0;
    private ISyncService mService;
    
    private ServiceConnection mConnection = new ServiceConnection() {

      public void onServiceConnected(ComponentName className, IBinder service) {
        Log.i("Notes", "Connected to sync service");
        mService = ISyncService.Stub.asInterface(service);
      }

      public void onServiceDisconnected(ComponentName arg0) {
        mService = null;
      }
    };

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mHandler = new Handler();
        setContentView(R.layout.main);
        
        /* Setup the cursor. */
        Cursor cursor = managedQuery(
            NotesProvider.List.CONTENT_URI,
            new String[] {
                NotesProvider.List.Columns._ID,
                NotesProvider.List.Columns.NAME},
            null,
            null,
            NotesProvider.List.Columns.NAME);
        
        ListAdapter adapter = new SimpleCursorAdapter(
            this,
            android.R.layout.simple_list_item_1,
            cursor,
            new String[] {NotesProvider.List.Columns.NAME},
            new int[] {android.R.id.text1});
        setListAdapter(adapter);
        
        refresh();
    }
    
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
      openList(id);
    }
    
    @Override
    protected void onDestroy() {
      super.onDestroy();
      unbindService(mConnection);
    }
    
    private String getListName(long id) {
      Cursor c = getContentResolver().query(
          NotesProvider.List.CONTENT_URI,
          new String[] {NotesProvider.List.Columns.NAME},
          NotesProvider.List.Columns._ID + "=?",
          new String[] {"" + id}, null);
      String name = null;
      if (c.moveToNext()) {
        name = c.getString(c.getColumnIndex(NotesProvider.List.Columns.NAME));
      }
      c.close();
      return name;
    }
    
    protected void openList(long id) {
      Intent intent = new Intent(
          Intent.ACTION_VIEW, ContentUris.withAppendedId(
              NotesProvider.List.CONTENT_URI, id));
      startActivity(intent);
    }

    /** Refreshes the main list of Notes. */
    private void refresh() {
      AccountManager accountManager = AccountManager.get(this);
      Account[] accounts = accountManager.getAccounts();
      if (accounts.length == 0) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage("No registered accounts.")
               .setCancelable(false)
               .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                 public void onClick(DialogInterface dialog, int id) {
                   Notes.this.finish();
                 }
               })
               .create().show();
        return;
      }
      
      /* For now, assume it is the first account on the system.
       * TODO(nav): Create an account picker?
       */
      accountManager.getAuthToken(accounts[0], SPREADSHEETS_AUTH_TOKEN_TYPE, true,
          new AccountManagerCallback<Bundle>() {
            public void run(AccountManagerFuture<Bundle> future) {
              Bundle bundle = null;
              try {
                bundle = future.getResult();
              } catch (OperationCanceledException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
              } catch (AuthenticatorException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
              } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
              }
              if (bundle == null) {
                return;
              }
              
              NotesApplication.getInstance().setSpreadsheetsAuth(
                  bundle.getString(AccountManager.KEY_ACCOUNT_NAME),
                  bundle.getString(AccountManager.KEY_AUTHTOKEN));
              
              Log.i("Notes", "Logged into documents service");
              
              /* Now bind. !*/
              bindService(new Intent(ISyncService.class.getName()),
                  mConnection, Context.BIND_AUTO_CREATE);
            }
      }, mHandler);
      
      accountManager.getAuthToken(accounts[0], DOCUMENTS_AUTH_TOKEN_TYPE,
          true,
          new AccountManagerCallback<Bundle>() {
            public void run(AccountManagerFuture<Bundle> future) {
              Bundle bundle = null;
              try {
                bundle = future.getResult();
              } catch (OperationCanceledException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
              } catch (AuthenticatorException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
              } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
              }
              if (bundle == null) {
                return;
              }
              Log.i("Notes", "Logged into documents server.");
              NotesApplication.getInstance().setDocumentsAuth(
                  bundle.getString(AccountManager.KEY_ACCOUNT_NAME),
                  bundle.getString(AccountManager.KEY_AUTHTOKEN));
            }
      }, mHandler);
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
      menu.add(0, MENU_NEW_LIST, 0, R.string.new_list);
      menu.add(0, MENU_SYNC, 0, R.string.sync);
      return true;
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
      switch (item.getItemId()) {
        case MENU_NEW_LIST:
          showDialog(DIALOG_NEW_LIST);
          return true;
        case MENU_SYNC:
          try {
            mService.startSync();
          } catch (RemoteException e) {
            showDialog(DIALOG_SYNC_ERROR);
          }
          return true;
      }
      return false;
    }

    @Override
    protected Dialog onCreateDialog(int id) {
      Dialog dialog;
      switch (id) {
        case DIALOG_NEW_LIST:
          dialog = new Dialog(this);
          LayoutInflater inflater = 
            (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE); 
          final View layout = inflater.inflate(R.layout.newlist_dialog,
              (ViewGroup) findViewById(R.id.layout_root));
          dialog.setContentView(layout);
          dialog.setTitle("New List");
          Button okButton = (Button) layout.findViewById(R.id.ok_button);
          final Dialog newListDialog = dialog;
          okButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
              EditText editText = (EditText) layout.findViewById(R.id.listname);
              createNewList(editText.getText().toString());
              newListDialog.dismiss();
            }
          });
          Button cancelButton = 
            (Button) layout.findViewById(R.id.cancel_button);
          cancelButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
              newListDialog.dismiss();
            }
          });
          break;
        case DIALOG_PROBLEM_CREATING_LIST:
          AlertDialog.Builder builder = new AlertDialog.Builder(this);
          dialog = builder.setMessage("Problem creating list.").create();
          break;
        case DIALOG_SYNC_ERROR:
          AlertDialog.Builder syncErrorBuilder = new AlertDialog.Builder(this);
          dialog = syncErrorBuilder.setMessage(R.string.dialog_sync_error).create();
          break;
        default:
          dialog = null;
      }
      return dialog;
    }
    
    @Override
    public void onCreateContextMenu(ContextMenu menu, View v,
        ContextMenuInfo menuInfo) {
      super.onCreateContextMenu(menu, v, menuInfo);
      menu.add(0, CONTEXT_DELETE, 0, R.string.delete);
    }
    
    @Override
    public boolean onContextItemSelected(MenuItem item) {
      AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
      switch (item.getItemId()) {
        case CONTEXT_DELETE:
          deleteList(info.id);
      }
      return false;
    }
    
    protected void deleteList(long id) {
      getContentResolver().delete(
          NotesProvider.List.CONTENT_URI,
          NotesProvider.List.Columns._ID + "=?",
          new String[] {"" + id});
    }

    protected void createNewList(String listName) {
      ContentValues values = new ContentValues();
      values.put(NotesProvider.List.Columns.NAME, listName);
      values.put(NotesProvider.List.Columns.LAST_MODIFIED,
          System.currentTimeMillis() / 1000);
      Uri uri =
        getContentResolver().insert(NotesProvider.List.CONTENT_URI, values);
      if (uri == null) {
        showDialog(DIALOG_PROBLEM_CREATING_LIST);
      }
      
      // TODO(nav): Update the display.
    }
}